import { shallowRef } from "vue";
import { FunctionExt } from "@antv/x6";
import type { Graph, Cell } from "@antv/x6";
import type { IFlowGraphContext } from "./create";

/**
 * 绑定相应事件
 * @param context
 */
export default function bindingEvent(context: Required<IFlowGraphContext>) {
	bindingGraphEvent(context);
	bindingKeyboard(context.graph);
}

/**
 * 显示/隐藏 节点链接桩
 * @param ports
 * @param show
 */
function setPorts(ports: NodeListOf<SVGAElement>, show: boolean) {
	for (let i = 0, len = ports.length; i < len; i = i + 1) {
		ports[i].style.visibility = show ? "visible" : "hidden";
	}
}

/**
 * 绑定graph事件
 * @param context
 */
function bindingGraphEvent(context: Required<IFlowGraphContext>) {
	const { graph, activePanel } = context;

	const createSetPorts = (flag: boolean) => {
		return () => {
			const { container } = graph;
			const ports = container.querySelectorAll(".x6-port-body") as NodeListOf<SVGAElement>;
			setPorts(ports, flag);
		};
	};
	const showPorts = createSetPorts(true);
	const hiddenPorts = createSetPorts(false);

	// 鼠标进入显示链接桩
	graph.on("node:mouseenter", FunctionExt.debounce(showPorts), 500);
	// 鼠标离开隐藏链接桩
	graph.on("node:mouseleave", hiddenPorts);
	graph.on("edge:mouseenter", showPorts);
	graph.on("edge:mouseleave", hiddenPorts);
	// 添加tools
	graph.on("edge:mouseleave", ({ cell }) => {
		cell.getTools()?.items.forEach((item: Cell.ToolItem) => {
			if (typeof item == "string") {
				cell.removeTool(item);
			} else {
				if (item.name !== "edge-editor") {
					cell.removeTool(item.name);
				}
			}
		});
	});

	// 点击出现配置面板
	graph.on("cell:selected", ({ cell }) => {
		const type = cell?.data?.type;
		if (context.activeCell) {
			context.activeCell.value = cell;
		} else {
			context.activeCell = shallowRef(cell);
		}
		activePanel.value = type ?? "";
	});

	// 点击清空清空面板
	graph.on("blank:click", () => {
		activePanel.value = "";
	});

	// 线条双击
	graph.on("edge:dblclick", ({ cell, e }) => {
		cell.addTools([{ name: "edge-editor", args: { event: e } }]);
	});
}

/**
 * 初始化键盘绑定
 */
function bindingKeyboard(graph: Graph) {
	// copy cut paste
	graph.bindKey(["meta+c", "ctrl+c"], () => {
		const cells = graph.getSelectedCells();
		if (cells.length) {
			graph.copy(cells);
		}
		return false;
	});
	graph.bindKey(["meta+x", "ctrl+x"], () => {
		const cells = graph.getSelectedCells();
		if (cells.length) {
			graph.cut(cells);
		}
		return false;
	});
	graph.bindKey(["meta+v", "ctrl+v"], () => {
		if (!graph.isClipboardEmpty()) {
			const cells = graph.paste({ offset: 32 });
			graph.cleanSelection();
			graph.select(cells);
		}
		return false;
	});

	//undo redo
	graph.bindKey(["meta+z", "ctrl+z"], () => {
		if (graph.history.canUndo()) {
			graph.history.undo();
		}
		return false;
	});
	graph.bindKey(["meta+shift+z", "ctrl+shift+z"], () => {
		if (graph.history.canRedo()) {
			graph.history.redo();
		}
		return false;
	});

	// select all
	graph.bindKey(["meta+a", "ctrl+a"], () => {
		const nodes = graph.getNodes();
		if (nodes) {
			graph.select(nodes);
		}
		return false;
	});

	//delete
	graph.bindKey("backspace", () => {
		const cells = graph.getSelectedCells();
		if (cells.length) {
			graph.removeCells(cells);
		}
	});
}
